#include "Sprite.h"
#include "il_assert.h"
#include <Iw2D.h>
#include <math.h>

Sprite::Sprite() 
	:m_image( NULL )
{ }

Sprite::~Sprite()
{
	IL_ASSERT( m_image == NULL, "the image of the sprite wasn't unloaded" );
}

void Sprite::Load( const char* name )
{
	IL_ASSERT( name != NULL, "tried to load a sprite with a NULL filename" );
	IL_ASSERT( m_image == NULL, "a image was previously loaded. Unload before you load a new one" );
	
	m_image = Iw2DCreateImageResource( name );
	IL_ASSERT( m_image != NULL, "failed to load the image from the ressource file %s", name );
}

void Sprite::Load( const char* name, int width )
{
	// load the whole texture
	Load( name );
	
	// setup the sprite sheet animations
	// calculate the number of frames
	// m_frames = m_image->GetWidth() / width;
	
	m_frame_size.x = width;
	m_frame_size.y = m_image->GetHeight();
}

void Sprite::Unload( )
{
	IL_ASSERT( m_image != NULL, "tried to unload a sprite but the image was already NULL" );
	
	delete m_image;
	m_image = NULL;
}

void Sprite::Update( float /*dt*/ )
{ }
		
void Sprite::Draw( const CIwSVec2& pos )
{
	Iw2DDrawImage( m_image, pos ); 
}

void Sprite::DrawStrip( const CIwSVec2& pos, float strip_width )
{
	Iw2DDrawImageRegion( m_image, pos, CIwSVec2(0,0), CIwSVec2( (int)(GetWidth() * strip_width), (int) GetHeight()) ); 
}

void Sprite::DrawStripCentered( const CIwSVec2& pos, float strip_width )
{
	CIwSVec2 pos_centered(
		(pos.x - m_image->GetWidth() / 2 ),
		(pos.y - m_image->GetHeight() / 2 ) );
		
	Iw2DDrawImageRegion( m_image, pos, CIwSVec2(0,0), CIwSVec2( (int)(GetWidth() * strip_width), (int)GetHeight()) ); 
}

void Sprite::DrawCentered( const CIwSVec2& pos )
{
	CIwSVec2 pos_centered(
		(pos.x - m_image->GetWidth() / 2 ),
		(pos.y - m_image->GetHeight() / 2 ) );
	
	Iw2DDrawImage( m_image, pos_centered ); 
}

void Sprite::DrawFrame( const CIwSVec2& pos, int frame )
{
	CIwSVec2 offset(m_frame_size.x * frame, 0 );

	Iw2DDrawImageRegion( m_image, pos, offset, m_frame_size );
}

void Sprite::DrawCenteredRotated( const CIwFVec2& pos, const CIwFVec2& orientation )
{
	IL_ASSERT( orientation.GetLengthSquared() != 0, "passed in orientation vector with length 0, this is no valid" );

	// calculate the roation in radians
	// marlades coordinate space is in opposite direction
	// so we have to use2PI - ()
	float rotation =  2.0f * PI - atan2f(orientation.x, orientation.y);
	
	CIwMat2D transform;
	
	// we use an alternative way, not described in the documentation
	// the doc says roate around the position of the object
	// this surely works but is inaccurate and causes instability
	// in the drawing, better way is to rotate around 0,0
	// and set the transform manually
	// when drawing we only have to make sure we draw the center of the image at 0/0
	// this way only one conversion is needed and more stability is archived
	// NOTE: we use the SetRot ( iwangle, bool ) overload explicitly 
	// because the center version alwys does the vector rotation
	// and the bool doesn't -> less compuations
	transform.SetRot( IW_ANGLE_FROM_RADIANS( rotation ), true );
	transform.t = CIwVec2( (int)pos.x, (int)pos.y);

	Iw2DSetTransformMatrix ( transform );
		// draw the image with the center at 0/0
		Iw2DDrawImage( m_image, CIwSVec2( -m_image->GetWidth() / 2, -m_image->GetHeight() / 2) ); 
	Iw2DSetTransformMatrix ( CIwMat2D::g_Identity );
}

float Sprite::GetWidth() const
{
	return m_image->GetWidth();
}

float Sprite::GetHeight() const
{
	return m_image->GetHeight();
}

CIwSVec2 Sprite::GetFrameSize() const
{
	return m_frame_size;
}